﻿/*
 * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
 */

#include "WifiBurnCtrl.h"
#include <QTextBlock>
#include <QMessageBox>
#include <QTimer>
#include <iostream>
#include <QFileInfo>
#include <QWaitCondition>
#include <QDateTime>
#include "BurnToolCommon/Global.h"
#include "SecureLink/Channel.h"
#include "Modem/YModem.h"
#include "DiaglogComSetting.h"
#include "DataConvertor.h"
#include "../platform/Securec/securec.h"
namespace  {
    unsigned char g_flashBootBurn[FLASH_BOOT_BURN_LEN] = { 0xEF, 0xBE, 0xAD, 0xDE, 0x12, 0x00,
                                                           0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00,
                                                           0x00, 0x00, 0x00, 0x00, 0x7c, 0x64 };
    const int MAX_RESSIZE = 1024;
    const int COMMON_TIMER_INTERVAL3000 = 3000;
    const int HEAD_PARITY_VALUE_TWO = 2;
    const int SLEEPTIME_100 = 100;
    const int SLEEPTIME_ADD_2500 = 2500;
    const int SLEEPTIME_50 = 50;
    const int CHECK_BIT = 3;
}
WifiBurnCtrl::WifiBurnCtrl(ChipType type, QObject *parent) : BurnCtrl(type, parent),
    m_packetSize(0),
    m_resSize(0),
    cCount(0),
    isPrePacket(false),
    countTimeOut(0),
    ackTimestamp(0)

{
    bootType = BOOT_ROM;
    isEraseMode = 0;
    isOnlyEraseAll = false;
}

WifiBurnCtrl::~WifiBurnCtrl()
{
}

long int WifiBurnCtrl::SlotCommunication(WPARAM srcData, LPARAM srcLen)
{
    PBYTE data = reinterpret_cast<PBYTE>(srcData);
    unsigned int len = static_cast<int>(srcLen);
    if (fsm == HI_BURN_FSM::FSM_NONE) {
        delete[] data; // 释放异步传入的原始数据内存
        data = nullptr;
        return 0;
    }
    len = len > MAX_BUFFER_LEN ? MAX_BUFFER_LEN : len;
    if (u32DataLen + len > MAX_BUFFER_LEN) {
        unsigned int oldLenWifi = u32DataLen;
        unsigned int discardLenWifi = u32DataLen + len - MAX_BUFFER_LEN;
        u32DataLen = oldLenWifi - discardLenWifi;
        if (memmove_s(cDataArray, MAX_BUFFER_LEN, cDataArray + discardLenWifi, u32DataLen) != 0) {
            delete[] data; // 释放异步传入的原始数据内存
            data = nullptr;
            return 0;
        }
    }
    if (memcpy_s(cDataArray + u32DataLen, MAX_BUFFER_LEN - u32DataLen, data, len) != 0) {
        delete[] data; // 释放异步传入的原始数据内存
        data = nullptr;
        return 0;
    }
    u32DataLen += len;
    bool isConnecting = false;
    if (fsm == HI_BURN_FSM::FSM_WAIT_SHAKE_HANDS_ACK || fsm == HI_BURN_FSM::FSM_WAIT_FLASH_SHAKE_HANDS_ACK) {
        isConnecting = true;
    }
    return SlotCommunicationSub(data, isConnecting, len);
}

long int WifiBurnCtrl::SlotCommunicationSub(PBYTE &data, bool &isConnecting, unsigned int len)
{
    if (fsm == HI_BURN_FSM::FSM_WORK) {
        SEBOOT_ACK_FRAME chlPktHead;
        int resDataLen = u32DataLen;
        int decodeResult = ChannelClass::Channel::DecodeSEBootAck(cDataArray, u32DataLen, chlPktHead, resDataLen);
        while (decodeResult == DECODE_PACKET_SUCCSS || decodeResult == DECODE_PACKET_MORE_THAN_ONE) {
            SecureZeroMemory(cDataArray + u32DataLen - resDataLen - sizeof(SEBOOT_ACK_FRAME), sizeof(SEBOOT_ACK_FRAME));
            if (memmove_s(cDataArray + u32DataLen - resDataLen - sizeof(SEBOOT_ACK_FRAME),
                sizeof(SEBOOT_ACK_FRAME) + resDataLen, cDataArray + (u32DataLen - resDataLen), resDataLen) != 0) {
                delete[] data; // 释放异步传入的原始数据内存
                data = nullptr;
                return 0;
            }
            u32DataLen = u32DataLen - sizeof(SEBOOT_ACK_FRAME);
            decodeResult = ChannelClass::Channel::DecodeSEBootAck(cDataArray, u32DataLen, chlPktHead, resDataLen);
        }
    }
    unsigned int i = 0;
    if (chipType == ChipType::HI3372 && u32DataLen > 100 && len == 1 && (data[0] == 0x06 || data[0] == 'C')) { // 100
        cDataArray[0] = data[0];
        u32DataLen = 1;
        singleLineWritingInfo.len = 0;
    }
    while (chipType == ChipType::HI3372 && i < u32DataLen && singleLineWritingInfo.len > 0) {
        if (memcmp(cDataArray + i, singleLineWritingInfo.singleLineData, CHECK_BIT) == 0) {
            if (u32DataLen - i < singleLineWritingInfo.len) {
                delete[] data; // 释放异步传入的原始数据内存
                data = nullptr;
                return 0;
            }
            if (memmove_s(cDataArray + i, singleLineWritingInfo.len,
                          cDataArray + i + singleLineWritingInfo.len,
                          u32DataLen - i - singleLineWritingInfo.len) == 0) {
                u32DataLen =  u32DataLen - i - singleLineWritingInfo.len;
                break;
            }
        }
        i++;
    }

    singleLineWritingInfo.len = 0;
    isProcessOk = false;
    ProcessReceiveData(cDataArray, u32DataLen);
    ParseData2CString(isConnecting);
    delete[] data; // 释放异步传入的原始数据内存
    data = nullptr;
    return 0;
}

void WifiBurnCtrl::ParseData2CStringSub(QString &strReceiveChar)
{
    QString strChar;
    for (unsigned int i = 0; i < u32DataLen; i++) {
        if (DataConvertor::IsVisibleAscii(cDataArray[i]) || cDataArray[i] == 0x6) {
            if (cDataArray[i] == 0x6) {
                continue;
            } else {
                strChar += cDataArray[i];
            }
        }
    }
    strReceiveChar += strChar;
}

void WifiBurnCtrl::ParseData2CString(bool isConnecting)
{
    if (isProcessOk && fsm > HI_BURN_FSM::FSM_WAIT_SEC_RESULT) {
        QString strReceiveChar;
        if (isConnecting) {
            SecureZeroMemory(cDataArray, sizeof(cDataArray));
            u32DataLen = 0;
        }
        if (u32DataLen < MAX_BUFFER_LEN) {
            ParseData2CStringSub(strReceiveChar);
        }
        if (!onlyBurnToolLog) {
            OutputString(strReceiveChar);
        }
        isProcessOk = false;
        SecureZeroMemory(cDataArray, sizeof(cDataArray));
        u32DataLen = 0;
    }
}

void WifiBurnCtrl::InitBurnCmd()
{
    InitBurnCmdByArray(infoArray);
}

void WifiBurnCtrl::InitBurnCmdByArray(const QMap<int, BIN_INFO> &infoArray)
{
    burnCmdArray.clear();
    burnCmdTypeArray.clear();
    burnCmdIndex = 0;
    QMap<int, BIN_INFO> tempWifiArray;
    filePathIndex = 0;
    QString strWifiSendData;
    bool isEraseAll = false;
    int i = 0;
    for (auto it = infoArray.begin(); it != infoArray.end(); it++) {
        BIN_INFO info = it.value();
        switch (info.type) {
            case IMAGE_TYPE::IMAGE_TYPE_LOADER: {
                strWifiSendData = "\n";
                burnCmdArray.push_back(strWifiSendData);
                burnCmdTypeArray[i] = (BurnCtrl::LOADER);
                SetFilePath(i, info.path);
                tempWifiArray[i] = info;
                break;
            }
            default: {
                if (!isOnlyEraseAll && !readEfuse) {
                    AddCmdByInfo(info, isEraseAll, tempWifiArray);
                    SetFilePath(i, info.path);
                }
                break;
            }
        }
        i++;
    }
    this->infoArray = tempWifiArray;
    if (isAutoBurn) {
        if (isOnlyEraseAll) {
            SEBOOT_DOWNLOAD_FLASHIMAGE st;
            st.eraseSize = 0xffffffff;
            st.fileAddr = 0;
            st.fileLen = 0;
            st.GetCrc();
            DataConvertor::Buf2ByteStr(reinterpret_cast<PBYTE>(&st), st.packetSize, strWifiSendData);
        } else if (readEfuse) {
            ReadEfuseSendPayload(strWifiSendData);
        } else {
            strWifiSendData = "\n";
        }
        burnCmdTypeArray[burnCmdTypeArray.size()] = BurnCtrl::END;
        burnCmdArray.push_back(strWifiSendData);
        strFilePathArray[strFilePathArray.size()] = "";
    }
    burnCmdIndex = 0;
}

void WifiBurnCtrl::ReadEfuseSendPayload(QString &strWifiSendData)
{
    SEBOOT_READ_OTP_EFUSE st;
    st.startBit = DataConvertor::Str2U32DecHex(startBit);
    st.bitWidth = DataConvertor::Str2U32DecHex(bitWidth);
    st.GetCrc();
    DataConvertor::Buf2ByteStr(reinterpret_cast<PBYTE>(&st), st.packetSize, strWifiSendData);
}

void WifiBurnCtrl::AddCmdByInfo(BIN_INFO info, bool &isEraseAll, QMap<int, BIN_INFO> &infoArray)
{
    bool isAllowed = false;
    for (int i = 0; i < burnFileName.size(); i++) {
        if (burnFileName[i] == info.fileName.toLower()) {
            isAllowed = true;
        }
    }
    if (!isAllowed && burnFileName.size() != 0) {
        return;
    }
    infoArray[infoArray.size()] = info;
    switch (info.type) {
        case IMAGE_TYPE::IMAGE_TYPE_EFUSE:
        case IMAGE_TYPE::IMAGE_TYPE_OTP: {
            HandleImageOTP(info);
            break;
        }
        case IMAGE_TYPE::IMAGE_TYPE_FACTORY: {
            HandleImageFactory(info, isEraseAll);
            break;
        }
        case IMAGE_TYPE::IMAGE_TYPE_VERSION: {
            HandleImageVer(info);
            break;
        }
        case IMAGE_TYPE::IMAGE_TYPE_KV_NV: { // 这里需要改成兼容
            if (isEraseMode == 0) {
                HandleImageKVNV(info, isEraseAll);
            } else {
                HandleImageOthers(info, isEraseAll);
            }
            break;
        }
        case IMAGE_TYPE::IMAGE_TYPE_NORMAL:
        case IMAGE_TYPE::IMAGE_TYPE_SECURITY_A:
        case IMAGE_TYPE::IMAGE_TYPE_SECURITY_B:
        case IMAGE_TYPE::IMAGE_TYPE_SECURITY_C:
        case IMAGE_TYPE::IMAGE_TYPE_PROTOCOL_A:
        case IMAGE_TYPE::IMAGE_TYPE_APPS_A:
        case IMAGE_TYPE::IMAGE_TYPE_RADIOCONFIG:
        case IMAGE_TYPE::IMAGE_TYPE_ROM:
        case IMAGE_TYPE::IMAGE_TYPE_EMMC:
        case IMAGE_TYPE::IMAGE_TYPE_FLASHBOOT_3892:
        default: {
            HandleImageOthers(info, isEraseAll);
            break;
        }
    }
}

void WifiBurnCtrl::HandleImageOTP(const BIN_INFO &info)
{
    QString strSendOTP;
    SEBOOT_DOWNLOAD_OTP_EFUSE st;
    st.fileLen = DataConvertor::Str2U32DecHex(info.fileSize);
    st.checkSum = ChannelClass::Channel::SopCrc16(reinterpret_cast<PBYTE>(&st), st.packetSize - 2); // crc16 len 2
    DataConvertor::Buf2ByteStr(reinterpret_cast<PBYTE>(&st), st.packetSize, strSendOTP);
    burnCmdArray.push_back(strSendOTP);
    burnCmdTypeArray[burnCmdTypeArray.size()] = BurnCtrl::BURN_CMD;
}

void WifiBurnCtrl::HandleImageVer(const BIN_INFO &info)
{
    QString strSendData;
    SEBOOT_DOWNLOAD_VERSION st;
    st.fileLen = DataConvertor::Str2U32DecHex(info.fileSize);
    st.checkSum = ChannelClass::Channel::SopCrc16(reinterpret_cast<PBYTE>(&st), st.packetSize - 2); // crc16 len 2
    DataConvertor::Buf2ByteStr(reinterpret_cast<PBYTE>(&st), st.packetSize, strSendData);
    burnCmdArray.push_back(strSendData);
    burnCmdTypeArray[burnCmdTypeArray.size()] = BurnCtrl::BURN_CMD;
}

void WifiBurnCtrl::HandleImageFactory(const BIN_INFO &info, bool &isEraseAll)
{
    QString strWifiSendFactory;
    SEBOOT_DOWNLOAD_FACTORYBIN stWifiFactory;
    stWifiFactory.fileLen = DataConvertor::Str2U32DecHex(info.fileSize);
    stWifiFactory.fileAddr = DataConvertor::Str2U32DecHex(info.burnAddr);
    stWifiFactory.eraseSize = DataConvertor::Str2U32DecHex(info.burnSize);
    if (stWifiFactory.eraseSize % 0x1000 != 0 && stWifiFactory.eraseSize < 0xf0ffffff) {
        stWifiFactory.eraseSize = 0x1000 * (stWifiFactory.eraseSize / 0x1000 + 1);
    }
    if (isEraseMode == 1) {
        stWifiFactory.eraseSize = !isEraseAll ? 0xffffffff : 0;
        isEraseAll = true;
    } else if (isEraseMode == 2) {  // erase all flag 2
        stWifiFactory.eraseSize = 0;
    }
    stWifiFactory.checkSum = ChannelClass::Channel::SopCrc16(
        reinterpret_cast<PBYTE>(&stWifiFactory), stWifiFactory.packetSize - 2); // crc16 len 2
    DataConvertor::Buf2ByteStr(reinterpret_cast<PBYTE>(&stWifiFactory), stWifiFactory.packetSize, strWifiSendFactory);
    burnCmdArray.push_back(strWifiSendFactory);
    burnCmdTypeArray[burnCmdTypeArray.size()] = BurnCtrl::BURN_CMD;
}

void WifiBurnCtrl::HandleImageKVNV(const BIN_INFO &info, bool &isEraseAll)
{
    QString strWifiSendKVNV;
    SEBOOT_DOWNLOAD_NV stWifiNv;
    stWifiNv.eraseSize = DataConvertor::Str2U32DecHex(info.burnSize);
    if (stWifiNv.eraseSize % 0x1000 != 0 && stWifiNv.eraseSize < 0xf0ffffff) {
        stWifiNv.eraseSize = 0x1000 * (stWifiNv.eraseSize / 0x1000 + 1);
    }
    if (isEraseMode == 1) {
        stWifiNv.eraseSize = !isEraseAll ? 0xffffffff : 0;
        isEraseAll = true;
    } else if (isEraseMode == 2) {  // erase all flag 2
        stWifiNv.eraseSize = 0;
    }
    stWifiNv.fileLen = DataConvertor::Str2U32DecHex(info.fileSize);
    stWifiNv.fileAddr = DataConvertor::Str2U32DecHex(info.burnAddr);
    stWifiNv.encItemCnt = 0;
    stWifiNv.flag = (isEraseMode == 0 || isEraseMode == 2) ? 0 : 1;   // erase all flag 2
    stWifiNv.checkSum = ChannelClass::Channel::SopCrc16(
        reinterpret_cast<PBYTE>(&stWifiNv), stWifiNv.packetSize - 2); // crc16 len 2
    DataConvertor::Buf2ByteStr(reinterpret_cast<PBYTE>(&stWifiNv), stWifiNv.packetSize, strWifiSendKVNV);
    burnCmdArray.push_back(strWifiSendKVNV);
    burnCmdTypeArray[burnCmdTypeArray.size()] = BurnCtrl::BURN_CMD;
}

void WifiBurnCtrl::HandleImageOthers(const BIN_INFO &info, bool &isEraseAll)
{
    QString strSendOthers;
    SEBOOT_DOWNLOAD_FLASHIMAGE stSdf;
    stSdf.eraseSize = DataConvertor::Str2U32DecHex(info.burnSize);
    if (stSdf.eraseSize % 0x1000 != 0 && stSdf.eraseSize < 0xf0ffffff) {
        stSdf.eraseSize = 0x1000 * (stSdf.eraseSize / 0x1000 + 1);
    }
    if (isEraseMode == 1) {
        stSdf.eraseSize = !isEraseAll ? 0xffffffff : 0;
        isEraseAll = true;
    } else if (isEraseMode == 2) { // erase all flag 2
        stSdf.eraseSize = 0;
    }
    stSdf.fileLen = DataConvertor::Str2U32DecHex(info.fileSize);
    stSdf.fileAddr = DataConvertor::Str2U32DecHex(info.burnAddr);
    if (info.type == IMAGE_TYPE::IMAGE_TYPE_ROM) {
        stSdf.formal = 2; // type rom 2
    } else if (info.type == IMAGE_TYPE::IMAGE_TYPE_EMMC) {
        stSdf.formal = 3; // type emmc 3
    }
    stSdf.formalReverse = ~stSdf.formal;
    stSdf.checkSum = ChannelClass::Channel::SopCrc16(
        reinterpret_cast<PBYTE>(&stSdf), stSdf.packetSize - 2); // crc16 len 2
    DataConvertor::Buf2ByteStr(reinterpret_cast<PBYTE>(&stSdf), stSdf.packetSize, strSendOthers);
    burnCmdArray.push_back(strSendOthers);
    burnCmdTypeArray[burnCmdTypeArray.size()] = BurnCtrl::BURN_CMD;
}

U32 WifiBurnCtrl::SendBurnCmd()
{
    U32 ret = ERR_SOP_SUCCESS;
    if (burnCmdArray.size() == 0) {
        return ERR_SOP_INVALID_PARAMETERS;
    }
    if (burnCmdArray.size() <= burnCmdIndex) {
        burnCmdIndex = 0;
    }
    BYTE payload[100] = { 0 }; // mac cmd len 100
    U32 len = 0;
    DataConvertor::ByteStr2Buf(burnCmdArray[burnCmdIndex], reinterpret_cast<PBYTE>(payload), len);
    if (GetCurrentCmdType() != BurnCtrl::LOADER) {
        if (isLoaderDfu && burnDlg != nullptr) {
            emit SignalSwitchDfu(0, 0);
            return 0;
        }
        WriteToPort(reinterpret_cast<char *>(payload), len); // 发送数据
    }
    oneBurnTime++;
    if (GetCurrentCmdType() == BurnCtrl::BURN_CMD) {
        modemPacketSize = modemPacketSizeBackup;
        ret = StartBurn();
    } else if (GetCurrentCmdType() == BurnCtrl::LOADER) {
        if (Global::currentChipTypeId == ChipType::SWAN) {
            if (isAutoBurn && !DataConvertor::CheckLoader(infoArray[burnCmdIndex], ackFlag)) {
                burnCmdIndex++;
                SendBurnCmd();
                return ret;
            }
        }
        modemPacketSize = MODEM_PACKET_SIZE;
        Sleep(SLEEPTIME_100); // 100ms
        SetResult(ERR_DOING);
        ret = BurnCtrl::StartBurn();
        SetProgressRange();
    } else if (GetCurrentCmdType() == BurnCtrl::END) {
        return HandleEndCmd();
    }
    burnCmdIndex++;
    return ret;
}

U32 WifiBurnCtrl::HandleEndCmd()
{
    if (isOneTimeBurn != 0) {
        int totalFileSize = 0;
        for (int i = 0; i < infoArray.size(); i++) {
            totalFileSize += DataConvertor::Str2U32DecHex(infoArray[i].fileSize);
        }
        burnFileSize = 0;
        UpdateProgress(static_cast<U32>(totalFileSize)); // 1024 bytes each package
        SetErrorString(*this, stringClass.GetUartBurnMode());
        SetErrorString(*this, stringClass.GetEraseMode().arg(m_eraseModeStr[isEraseMode]));
        SetEditErrorString(IDS_STRING_32879);
        SetEditErrorString(stringClass.GetIdsString32880());
        SetEditErrorString(IDS_STRING_32879);
        SetResult(0);
        QTime timer = QTime::currentTime().addMSecs(1000);  // 1000ms后
        while (QTime::currentTime() < timer) {
            QCoreApplication::processEvents(QEventLoop::AllEvents, 100); // 执行100ms
        }
        if (isReset) {
            SetEditErrorString("reset device");
            ResetByCmd();
        }
        Global::CloseApp(this->result);
        return ERR_SOP_SUCCESS;
    }
    if (chipType == ChipType::WIFI4GCAT1) {
        SetErrorString(*this, stringClass.GetUartBurnMode());
        SetErrorString(*this, stringClass.GetEraseMode().arg(m_eraseModeStr[isEraseMode]));
    }
    SetEditErrorString(IDS_STRING_32879);
    SetEditErrorString(stringClass.GetIdsString32880());
    SetEditErrorString(IDS_STRING_32879);
    SetResult(0);
    burnCmdIndex++;
    connectConfirmTime = 0;
    if (isResetAfterSuccess) {
        ResetByCmd();
    }
    SetFsm(HI_BURN_FSM::FSM_CHECK_IF_CONNECT);
    SetTimerByFsm();
    SendCtrl();
    if (isAutoDisconnect && isAutoBurn) {
        ResetByCmd();
    } else if (isAutoDisconnect) {
        WifiState();
    }
    return ERR_SOP_SUCCESS;
}

void WifiBurnCtrl::ReceiveDataMulFsm(PBYTE data, unsigned int &dataLen)
{
    if (fsm == HI_BURN_FSM::FSM_WAIT_SHAKE_HANDS_ACK ||
        fsm == HI_BURN_FSM::FSM_CHECK_IF_CONNECT ||
        fsm == HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_END_ACK ||
        fsm == HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_RESET_ACK ||
        fsm == HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_LOCK_ACK ||
        fsm == HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_READ_EFUSE_ACK ||
        fsm == HI_BURN_FSM::FSM_BURN_UPLOAD_END_ACK) {
        HandleMulFsmAck(dataLen, data);
    } else {
        BurnCtrl::ProcessReceiveData(data, dataLen);
    }
}

U32 WifiBurnCtrl::StartBurn()
{
    if (!isConnect) {
        return ERR_SOP_CPAB_NOT_CONNECT_UE;
    }

    if (GetBurnFsm() >= HI_BURN_FSM::FSM_BURN_WAIT_START_C && GetBurnFsm() <= HI_BURN_FSM::FSM_BURN_WAIT_ZERO_ACK) {
        return ERR_SOP_BUSY;
    }
    SetFileInfo(GetCurrentFilePath());
    QFileInfo fileInfo(strFilePath);
    strFileName = fileInfo.fileName();
    fileSize = fileInfo.size();
    strFileSize = QString::number(fileSize);
    if (fileSize <= 0) {
        if (isOneTimeBurn != 0) {
            result = ERR_FILE_NOT_FOUND;
            Global::CloseApp(result);
        }
        return ERR_SOP_FILE_NOT_FOUND;
    }
    EnterCS();
    SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_DOWN_ACK);
    SetTimerByFsm();
    LeaveCS();
    return ERR_SOP_SUCCESS;
}

void WifiBurnCtrl::ResetUIAndFSM()
{
    QString strReceiveChar;
    if (u32DataLen < MAX_BUFFER_LEN) {
        for (unsigned int i = 0; i < u32DataLen; i++) {
            if (DataConvertor::IsVisibleAscii(cDataArray[i]) || cDataArray[i] == 0x6) {
                strReceiveChar += cDataArray[i];
            }
        }
    }

    OutputString(strReceiveChar);
    isProcessOk = false;
    singleLineWritingInfo.len = 0;
    BurnCtrl::ResetUIAndFSM();
    oneBurnTime = 0;
}

void WifiBurnCtrl::SetEraseMode(int eraseMode)
{
    isEraseMode = eraseMode;
}

void WifiBurnCtrl::SetOnlyEraseAll(bool eraseAll)
{
    isOnlyEraseAll = eraseAll;
}

void WifiBurnCtrl::StartUpload(QString output, U32 addr, U32 size)
{
    SlotKillAllTimer();
    QString cleanPath = QDir::cleanPath(output);
    if (cleanPath.isEmpty()) {
        return;
    }
    m_uploadFile.setFileName(cleanPath);
    if (m_uploadFile.exists()) {
        // 存在
        if (!isExport) {
            int result = QMessageBox::information(nullptr, stringClass.GetInformation(),
                                                  stringClass.GetIdsString32883(),
                                                  stringClass.GetYes(), stringClass.GetNo());
            if (result == 1) {
                return;
            }
        }

        m_uploadFile.remove();
    }

    if (m_uploadFile.open(QIODevice::ReadWrite | QIODevice::Truncate) == 0) {
        SetEditErrorString(stringClass.GetIdsString32809());
        ResetByMode();
        return;
    }

    SEBOOT_UPLOAD_DATA st;
    st.fileAddr = addr;
    st.fileLen = size;
    st.GetCrc();
    u32DataLen = 0;
    SecureZeroMemory(cDataArray, sizeof(cDataArray));
    WriteToPort(reinterpret_cast<char *>(&st), st.packetSize);
    SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_UPLOAD_ACK);
    SetTimerByFsm();
}

void WifiBurnCtrl::ReadEfuse(U32 addr, U32 size)
{
    SEBOOT_READ_OTP_EFUSE st;
    st.startBit = addr;
    st.bitWidth = size;
    st.GetCrc();
    WriteToPort(reinterpret_cast<char *>(&st), st.packetSize);
    SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_READ_EFUSE_ACK);
    SetTimerByFsm();
}

void WifiBurnCtrl::YmodemPrepareIntialPacket(PBYTE &pBurnFileInfo, int &pktLen)
{
    if (infoArray.size() > burnCmdIndex - 1) {
        SetEditErrorString("\r\n" + infoArray[burnCmdIndex - 1].fileName);
    }
    SetEditErrorString(stringClass.GetIdsString32882());
    int packetLen = 133; // start packet 133 len
    pktLen = packetLen;
    // 在内部分配空间，必须传指针的引用.
    pBurnFileInfo = new unsigned char[packetLen];
    if (pBurnFileInfo == nullptr) {
        return;
    }
    SecureZeroMemory(pBurnFileInfo, packetLen);

    pBurnFileInfo[0] = MODEM_SOH;
    pBurnFileInfo[1] = pkgNum;
    pBurnFileInfo[2] = 0xff - pkgNum; // 第2位固定值
    pkgNum++;

    WORD crc;
    int i = 3;

    strFileName = infoArray[burnCmdIndex - 1].fileName;
    if (strFileName.length() < 0xfffffff) {
        for (int j = 0; j < strFileName.length(); j++) {
            pBurnFileInfo[i++] = strFileName.toLatin1().data()[j];
        }
    }
    pBurnFileInfo[i++] = 0x00;

    strFileSize = infoArray[burnCmdIndex - 1].fileSize;
    fileSize = DataConvertor::Str2U32DecHex(strFileSize);
    if (strFileSize.length() < 0xfffffff) {
        for (int j = 0; j < strFileSize.length(); j++) {
            pBurnFileInfo[i++] = strFileSize.toLatin1().data()[j];
        }
    }
    crc = YModemClass::YModem::GetCrc(&pBurnFileInfo[3], 128);           // 从第3字节开始计算128字节的crc
    pBurnFileInfo[131] = static_cast<unsigned char>(crc >> 8); // 131为crc高字节，右移8位
    pBurnFileInfo[132] = static_cast<unsigned char>(crc);        // 132为crc低字节
}

void WifiBurnCtrl::ResetByCmd()
{
    SEBOOT_RESET st;
    st.GetCrc();
    WriteToPort(reinterpret_cast<char *>(&st), st.packetSize);
    if (isResetAfterSuccess && !isAutoDisconnect) {
        Sleep(SLEEPTIME_100);
        return;
    }
    if (isAutoDisconnect) {
        Sleep(SLEEPTIME_100);
        if (chipType == ChipType::WIFI4GCAT1) {
            Sleep(SLEEPTIME_ADD_2500);
        }
        WifiState();
        return;
    }
    if (portType == Base::SERIAL_PORT) {
        Sleep(SLEEPTIME_100);
    }
    SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_RESET_ACK);
    SetTimerByFsm();
}

void WifiBurnCtrl::AtReset(QString cmd)
{
    WriteToPort(cmd.toLatin1(), cmd.size());
}

void WifiBurnCtrl::SwitchToDfu()
{
    SEBOOT_SWITCH_DFU st;
    st.GetCrc();
    WriteToPort(reinterpret_cast<char *>(&st), st.packetSize);
}

void WifiBurnCtrl::EraseAllByCmd()
{
    SEBOOT_DOWNLOAD_FLASHIMAGE st;
    st.eraseSize = 0xffffffff;
    st.fileAddr = 0;
    st.fileLen = 0;
    st.GetCrc();
    WriteToPort(reinterpret_cast<char *>(&st), st.packetSize);
    SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_RESET_ACK);
    SetTimerByFsm();
}

void WifiBurnCtrl::SetProgressRange()
{
    int totalFileSize = 0;
    for (int i = 0; i < infoArray.size(); i++) {
        if (isLoaderDfu && infoArray[i].type != IMAGE_TYPE::IMAGE_TYPE_LOADER) {
            continue;
        }
        totalFileSize += DataConvertor::Str2U32DecHex(infoArray[i].fileSize);
    }
    BurnCtrl::SetProgressRange(0, SHRT_MAX);
    burnFileSize = 0;
    UpdateProgress(0, totalFileSize);
}

void WifiBurnCtrl::UpdateProgress(UINT progress)
{
    BurnCtrl::SetProgressValue(progress);
    NotifyState(static_cast<int>(fsm), progress);
    QString progressStr = "progress[" + QString::number(static_cast<float>(progress) /
                                                        static_cast<float>(SHRT_MAX) * 100, 'f', 2) + "%]\r\n";
    std::cout<<progressStr.toStdString();
}

void WifiBurnCtrl::UpdateProgress(U32 fileSize, UINT totalWifiFileSize)
{
    if (totalWifiFileSize == 0) {
        for (int i = 0; i < infoArray.size(); i++) {
            if (isLoaderDfu && infoArray[i].type != IMAGE_TYPE::IMAGE_TYPE_LOADER) {
                continue;
            }
            totalWifiFileSize += DataConvertor::Str2U32DecHex(infoArray[i].fileSize);
        }
    }
    UINT progress = 0;
    burnFileSize += fileSize;
    if (burnFileSize == static_cast<int>(totalWifiFileSize)) {
        progress = SHRT_MAX;
        burnFileSize = 0;
    } else if (burnFileSize == 0 || totalWifiFileSize == 0) {
        progress = 0;
    } else {
        progress = (static_cast<float>(burnFileSize) / totalWifiFileSize) * SHRT_MAX;
    }
    UpdateProgress(progress);
}

void WifiBurnCtrl::ProceSeloaderEndAck(QString &strData, const SEBOOT_ACK_FRAME &chlPktHead)
{
    RmoveTimerKey();
    strData.clear();
    pkgNum = 0x0;
    isProcessOk = true;
    SetFsm(HI_BURN_FSM::FSM_WORK);
    if (chlPktHead.result == 0xA5 || chlPktHead.result == 0x00) {
        burnCmdIndex = 0;
        SetResult(ERR_SELOADER_ACK_IS_FAIL);
        if (isOneTimeBurn != 0) {
            Global::CloseApp(this->result);
        }
        return;
    }
    Sleep(10); // 延时10ms
    if (isOneTimeBurn != 0 && burnCmdIndex >= burnCmdArray.size()) {
        Global::CloseApp(this->result);
        return;
    }

    oneBurnTime = 0;
    if ((isAutoBurn || burnCmdArray.size() > burnCmdIndex) && !isExport) {
        SendBurnCmd();
    } else {
        SetTimerByFsm();
    }

    if (isExport) {
        SetEditErrorString(tr("Seloader_soc_sign_enc.bin being programmed."));
        SetEditErrorString(tr("Start export."));
        StartUpload(exportTarget, DataConvertor::Str2U32DecHex(exportAddr), DataConvertor::Str2U32DecHex(exportSize));
    }
    return;
}

void WifiBurnCtrl::ProceIfConnect()
{
    SlotKillAllTimer();

    isConnect = true;
    isProcessOk = true;
    Sleep(connectConfirmSleepTimeout);
    SecureZeroMemory(cDataArray, u32DataLen);
    u32DataLen = 0;
    if (isShutDown) {
        return;
    }
    SendCtrl();
    SetTimerByFsm();
    return;
}

void WifiBurnCtrl::ProceShakeHand()
{
    SlotKillAllTimer();
    SEBOOT_SHAKE_HANDS_FRAME *head = reinterpret_cast<SEBOOT_SHAKE_HANDS_FRAME *>(Global::shakeHandSignal);
    this->baud = head->baudRate;
    qDebug()<<head->baudRate<<this;
    this->databits = head->dataBits;
    this->stopbits = head->stopBits;
    if (head->parity == HEAD_PARITY_VALUE_TWO) {
        parity = QSerialPort::EvenParity; // even check trans to 2
    } else if (head->parity == 1) {
        parity = QSerialPort::OddParity;
    } else {
        parity = QSerialPort::NoParity;
    }
    flowctrl = head->flowctrl;
    BurnCtrl::BurnCmdType type = GetCurrentCmdType();
    if (!isSwitchAfterLoader || type != BurnCmdType::LOADER) {
        UpdateComSettingWithoutClose();
    }

    port.SetOneTimeReadByte(0);
    isConnect = true;
    // 设置fsm之前要判断是否符合预期
    SetFsm(HI_BURN_FSM::FSM_WORK);
    AddLog("connect success");
    isProcessOk = true;

    if (isAutoBurn || (burnCmdArray.size() > burnCmdIndex && oneBurnTime != 0)) {
        Sleep(SLEEPTIME_100); // 100ms
        SendBurnCmd();
    }
    SecureZeroMemory(cDataArray, u32DataLen);
    u32DataLen = 0;
}

void WifiBurnCtrl::TimeoutProcess()
{
    if (fsm == HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_END_ACK) {
        QString strData;
        SEBOOT_ACK_FRAME chlPktHead;
        memset_s(&chlPktHead, sizeof(SEBOOT_ACK_FRAME), 0, sizeof(SEBOOT_ACK_FRAME));
        ProceSeloaderEndAck(strData, chlPktHead);
    } else if (fsm == HI_BURN_FSM::FSM_CHECK_IF_CONNECT) {
        ProceIfConnect();
    }
}

void WifiBurnCtrl::ProcessReceiveData(PBYTE data, unsigned int &dataLen)
{
    if (data == nullptr || dataLen > MAX_BUFFER_LEN) {
        return;
    }

    switch (fsm) {
        case HI_BURN_FSM::FSM_WAIT_FLASH_SHAKE_HANDS_ACK:
            HandleFlashShakeHandsAck(dataLen, data, (interruptFlag.size() + 1));
            break;
        case HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_DOWN_ACK:
            HandleSeloadDownAck(dataLen, data);
            break;
        case HI_BURN_FSM::FSM_BURN_WAIT_START_C:
            HandleWaitStartC(dataLen, data);
            break;
        case HI_BURN_FSM::FSM_BURN_WAIT_INIT_ACK:
            HandleWaitInitAck(dataLen, data);
            break;
        case HI_BURN_FSM::FSM_BURN_WAIT_INTER_ACK:
            HandleInterAck(dataLen, data);
            break;
        case HI_BURN_FSM::FSM_BURN_WAIT_FINAL_ACK:
            HandleFinalAck(dataLen, data);
            break;
        case HI_BURN_FSM::FSM_BURN_WAIT_ZERO_ACK:
            HandleZeroAck(dataLen, data);
            break;
        case HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_UPLOAD_ACK:
            HandleSeloadUploadAck(dataLen, data);
            break;
        case HI_BURN_FSM::FSM_BURN_UPLOAD_START_C:
            HandleUploadStartC(dataLen, data);
            break;
        case HI_BURN_FSM::FSM_BURN_UPLOAD_INIT_ACK: // 等待数据包1029，回复0x06 等待0x04,回复C
            HandleUploadInitAck(dataLen, data);
            break;
        case HI_BURN_FSM::FSM_BURN_UPLOAD_EOT_C: // 等待结束包133,回复0x06
            HandleUploadEotC(dataLen, data);
            break;
        case HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_CHANGE_BAUD:
            HandleChangeBaud(dataLen, data);
            break;
        default:
            ReceiveDataMulFsm(data, dataLen);
            break;
    }
}

void WifiBurnCtrl::HandleChangeBaud(unsigned int &dataLen, PBYTE data)
{
    SEBOOT_ACK_FRAME chlPktHead;
    int resDataLen = dataLen;
    int decodeResult = ChannelClass::Channel::DecodeSEBootAck(data, dataLen, chlPktHead, resDataLen);
    if (decodeResult == DECODE_PACKET_SUCCSS || decodeResult == DECODE_PACKET_MORE_THAN_ONE) {
        SecureZeroMemory(data + dataLen - resDataLen - sizeof(SEBOOT_ACK_FRAME), sizeof(SEBOOT_ACK_FRAME));
        if (memmove_s(data + dataLen - resDataLen - sizeof(SEBOOT_ACK_FRAME),
            sizeof(SEBOOT_ACK_FRAME) + resDataLen, data + (dataLen - resDataLen), resDataLen) != 0) {
            return;
        }
        dataLen = dataLen - sizeof(SEBOOT_ACK_FRAME);
        if (chlPktHead.result == 0xA5 || chlPktHead.result == 0x00) {
            burnCmdIndex = 0;
            SetResult(ERR_SELOADER_ACK_IS_FAIL);
            if (isOneTimeBurn != 0) {
                Global::CloseApp(this->result);
            }
            return;
        }
        QString strData;
        UpdateComSettingWithoutClose();
        Sleep(SLEEPTIME_50);
        ProceSeloaderEndAck(strData, chlPktHead);
    }
}

void WifiBurnCtrl::HandleZeroAck(unsigned int &dataLen, PBYTE data)
{
    if (DataConvertor::FindChar(data, dataLen, MODEM_ACK)) { // 文件传输完毕，发送"EOT"
        RmoveTimerKey();
        pkgNum = 0x0;
        EnterCS();
        if (fsm == HI_BURN_FSM::FSM_BURN_WAIT_ZERO_ACK) {
            SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_END_ACK);
            SetTimerByFsm();
        }
        LeaveCS();
        isProcessOk = false;
        ProcessReceiveData(data, dataLen);
    }
}

void WifiBurnCtrl::HandleWaitStartC(unsigned int &dataLen, PBYTE data)
{
    if (DataConvertor::FindChar(data, dataLen, MODEM_C)) { // 检测升级信号并发送头包
        RmoveTimerKey();
        unsigned char *pBurnFileInfo = nullptr;
        int pktLen;
        YmodemPrepareIntialPacket(pBurnFileInfo, pktLen);
        WriteToPort(reinterpret_cast<char *>(pBurnFileInfo), pktLen);
        delete[] pBurnFileInfo;
        isProcessOk = true;
        EnterCS();
        if (fsm == HI_BURN_FSM::FSM_BURN_WAIT_START_C) {
            SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_INIT_ACK);
            SetTimerByFsm();
        }
        LeaveCS();
    }
}

void WifiBurnCtrl::HandleFlashShakeHandsAck(unsigned int &dataLen, PBYTE data, int interFlagSize)
{
    for (unsigned int i = 0; i < dataLen; i++) {
        if (data[i] == 0) {
            data[i] = ' ';
        }
    }
    QString strData = QString::fromLatin1(reinterpret_cast<CHAR *>(data));
    unsigned char flag[5] = { 0xef, 0xbe, 0xad, 0xde, 0x00 }; // len 5
    if (strData.indexOf(QString::fromLatin1(reinterpret_cast<CHAR *>(flag))) != -1) {
        SlotKillAllTimer();
        strData.clear();
        port.SetOneTimeReadByte(0);
        isConnect = true;
        isProcessOk = true;
        SetFsm(HI_BURN_FSM::FSM_WORK);
        char ctrlC[1] = { 3 }; // 3 ctrl + c
        WriteToPort(ctrlC, 1);
    } else {
        if (static_cast<int>(dataLen) > interFlagSize) {
            u32DataLen = interFlagSize;
            if (memmove_s(cDataArray, sizeof(cDataArray), cDataArray + (dataLen - interFlagSize), interFlagSize) != 0) {
                return;
            }
        }
    }
}

void WifiBurnCtrl::HandleWaitInitAck(unsigned int &dataLen, PBYTE data)
{
    for (unsigned int i = 0; i < dataLen; i++) {
        data[i] = (data[i] == 0 ? ' ' : data[i]);
    }
    QString cleanPath = QDir::cleanPath(strFilePath);
    if (cleanPath.isEmpty()) {
        return;
    }
    binFile.setFileName(cleanPath);
    if (DataConvertor::FindChar(data, dataLen, MODEM_ACK)) { // 检测确认回复信号并发送文件
        PartOfHandleWaitInitAck();
    } else if (dataLen == 1 && DataConvertor::FindChar(data, dataLen, MODEM_C)) {
        HandleWaitInitAckSub();
    } else {
        ResetData(dataLen, data);
    }
}

void WifiBurnCtrl::PartOfHandleWaitInitAck()
{
    RmoveTimerKey();
    BIN_INFO info = infoArray[burnCmdIndex - 1]; // CFile::modeRead
    if (IsEncrypt()) {
        memoryOperation.SetEncrypt(encryptBuffer, encryptBufferLen);
    } else if (binFile.open(QIODevice::ReadOnly | QIODevice::Truncate) == 0) {
        SetEditErrorString(stringClass.GetIdsString32809());
        ResetByMode();
        SetResult(ERR_OPEN_FILE);
        return;
    }

    int pktLen = modemPacketSize + 5; // 1029长度
    PBYTE pBurnFile = new BYTE[pktLen];
    if (pBurnFile == nullptr) {
        return;
    }
    SecureZeroMemory(pBurnFile, pktLen);
    pBurnFile[0] = ChannelClass::Channel::GetYmodeSTX(modemPacketSize);
    pBurnFile[1] = pkgNum;
    pBurnFile[2] = 0xff - pkgNum; // 第2字节固定含义
    pkgNum++;
    U32 readBytes = modemPacketSize; // 默认读1024字节
    UINT nBytesRead = 0;
    HandleWaitInitAckRead(info, readBytes, nBytesRead, pBurnFile);
    /* 计算1024字节crc从第3字节开始 */
    WORD crc = YModemClass::YModem::GetCrc(reinterpret_cast<PBYTE>(&pBurnFile[3]), modemPacketSize); // 3
    pBurnFile[pktLen - 2] = static_cast<unsigned char>(crc >> 8);           // crc右移8位放在1027上
    pBurnFile[pktLen - 1] = static_cast<unsigned char>(crc);                  // crc低位放在1028位
    singleLineWritingInfo.len = pktLen;
    memcpy_s(singleLineWritingInfo.singleLineData, CHECK_BIT, pBurnFile, CHECK_BIT);
    WriteToPort(reinterpret_cast<char *>(pBurnFile), pktLen);
    UpdateProgress(readBytes);
    isProcessOk = true;
    EnterCS();
    if (fsm == HI_BURN_FSM::FSM_BURN_WAIT_INIT_ACK) {
        SetFsm(nBytesRead < modemPacketSize ? HI_BURN_FSM::FSM_BURN_WAIT_FINAL_ACK :
                                              HI_BURN_FSM::FSM_BURN_WAIT_INTER_ACK); // 长度1024字节
        SetTimerByFsm();
    }
    LeaveCS();
    if (pBurnFile != nullptr) {
        delete [] pBurnFile;
        pBurnFile = nullptr;
    }
}

void WifiBurnCtrl::HandleWaitInitAckRead(const BIN_INFO &info, U32 &readBytes, UINT &nBytesRead, PBYTE pBurnFile)
{
    if (IsEncrypt()) {
        memoryOperation.Seek(info.GetFileIndex());
        if (memoryOperation.Pos() + modemPacketSize > info.GetFileIndex() + info.GetFileSize()) {
            readBytes = static_cast<U32>(info.GetFileIndex() + info.GetFileSize() - memoryOperation.Pos()); // 1024
        }
        nBytesRead = memoryOperation.Read(pBurnFile + 3, readBytes); // 读1024字节到偏移3字节之后
    } else {
        binFile.seek(info.GetFileIndex());
        if (binFile.pos() + modemPacketSize > info.GetFileIndex() + info.GetFileSize()) {
            readBytes = static_cast<U32>(info.GetFileIndex() + info.GetFileSize() - binFile.pos()); // 1024
        }
        nBytesRead = binFile.read(reinterpret_cast<CHAR *>(pBurnFile) + 3, readBytes); // 读1024字节到偏移3字节之后
    }
}

void WifiBurnCtrl::ResetData(unsigned int &dataLen, PBYTE data) const
{
    SecureZeroMemory(data, dataLen);
    dataLen = 0;
}

void WifiBurnCtrl::HandleWaitInitAckSub()
{
    unsigned char *pBurnFileInfo = nullptr;
    int pktLen;
    pkgNum = 0;
    YmodemPrepareIntialPacket(pBurnFileInfo, pktLen);
    singleLineWritingInfo.len = pktLen;
    memcpy_s(singleLineWritingInfo.singleLineData, CHECK_BIT, pBurnFileInfo, CHECK_BIT);
    WriteToPort(reinterpret_cast<char *>(pBurnFileInfo), pktLen);
    delete[] pBurnFileInfo;
    isProcessOk = true;
}

void WifiBurnCtrl::HandleSeloadDownAck(unsigned int &dataLen, PBYTE data)
{
    if (dataLen < SEBOOT_ACK_LEN) {
        if (dataLen >= 1 && DataConvertor::FindChar(data, dataLen, MODEM_C)) {
            ResetFsm2StartC();
        }
        return;
    }
    SEBOOT_ACK_FRAME chlPktHeadVal;
    int resDataLen = dataLen;
    int decodeResult = ChannelClass::Channel::DecodeSEBootAck(data, dataLen, chlPktHeadVal, resDataLen);
    if (decodeResult == DECODE_PACKET_SUCCSS || decodeResult == DECODE_PACKET_MORE_THAN_ONE) {
        SecureZeroMemory(data + dataLen - resDataLen - sizeof(SEBOOT_ACK_FRAME), sizeof(SEBOOT_ACK_FRAME));
        if (memmove_s(data + dataLen - resDataLen - sizeof(SEBOOT_ACK_FRAME),
            sizeof(SEBOOT_ACK_FRAME) + resDataLen, data + (dataLen - resDataLen), resDataLen) != 0) {
            return;
        }
        dataLen = dataLen - sizeof(SEBOOT_ACK_FRAME);
        if (chlPktHeadVal.result == 0xA5) {
            QString strPrompt;
            strPrompt = stringClass.GetIdsString32890().arg(chlPktHeadVal.errorCode);
            SlotKillAllTimer();
            SetEditErrorString(strPrompt);
            SetFsm(HI_BURN_FSM::FSM_WORK);
            isProcessOk = true;
            SetResult(ERR_SELOADER_ACK_IS_FAIL);
            burnCmdIndex = 0;
            if (isOneTimeBurn != 0) {
                Global::CloseApp(this->result);
            }
            return;
        } else {
            ResetFsm2StartC();
            if (dataLen > 0 && cDataArray[dataLen - 1] == MODEM_C) {
                ProcessReceiveData(data, dataLen);
            }
        }
    } else if (dataLen >= 1 && DataConvertor::FindChar(data, dataLen, MODEM_C)) {
        ResetFsm2StartC();
    }
}

void WifiBurnCtrl::ResetFsm2StartC()
{
    SlotKillAllTimer();
    EnterCS();
    if (fsm == HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_DOWN_ACK) {
        SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_START_C);
        SetTimerByFsm();
    }
    LeaveCS();
    isProcessOk = true;
}

void WifiBurnCtrl::HandleMulFsmAckSub()
{
    if (fsm == HI_BURN_FSM::FSM_WAIT_SHAKE_HANDS_ACK) {
        if (cDataArray[u32DataLen] == MODEM_C) {
            ProceShakeHand();
        }
    }
}

void WifiBurnCtrl::HandleMulFsmAck(unsigned int &dataLen, PBYTE data)
{
    if (dataLen < SEBOOT_ACK_LEN) {
        HandleMulFsmAckSub();
        return;
    }
    SEBOOT_ACK_FRAME chlPktHead;
    int resDataLen = dataLen;
    int decodeResult = ChannelClass::Channel::DecodeSEBootAck(data, dataLen, chlPktHead, resDataLen);
    while (decodeResult == DECODE_PACKET_SUCCSS || decodeResult == DECODE_PACKET_MORE_THAN_ONE) {
        SecureZeroMemory(data + dataLen - resDataLen - sizeof(SEBOOT_ACK_FRAME), sizeof(SEBOOT_ACK_FRAME));
        if (memmove_s(data + dataLen - resDataLen - sizeof(SEBOOT_ACK_FRAME),
            sizeof(SEBOOT_ACK_FRAME) + resDataLen, data + (dataLen - resDataLen), resDataLen) != 0) {
            return;
        }
        dataLen = dataLen - sizeof(SEBOOT_ACK_FRAME);
        if (chlPktHead.frameType != UART_ACK_FRAME || chlPktHead.packetSize != sizeof(SEBOOT_ACK_FRAME)) {
            if (decodeResult == DECODE_PACKET_MORE_THAN_ONE) {
                decodeResult = ChannelClass::Channel::DecodeSEBootAck(data, dataLen, chlPktHead, resDataLen);
                continue;
            } else {
                return;
            }
        }
        if (fsm == HI_BURN_FSM::FSM_WAIT_SHAKE_HANDS_ACK) {
            if (chlPktHead.result != 0xA5) {
                ackFlag = chlPktHead.errorCode;
                ProceShakeHand();
                break;
            }
            if (decodeResult == DECODE_PACKET_MORE_THAN_ONE) {
                decodeResult = ChannelClass::Channel::DecodeSEBootAck(data, dataLen, chlPktHead, resDataLen);
                continue;
            } else {
                return;
            }
            burnCmdIndex = 0;
            return;
        } else {
            QString strData = QString::fromLatin1(reinterpret_cast<CHAR *>(data));
            HandleMulFsmAckP1(strData, chlPktHead);
        }
        break;
    }
}

void WifiBurnCtrl::HandleMulFsmAckP1(QString &strData, SEBOOT_ACK_FRAME &chlPktHead)
{
    if (fsm == HI_BURN_FSM::FSM_CHECK_IF_CONNECT) {
        connectConfirmTime = 0;
        ProceIfConnect();
        return;
    } else if (fsm == HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_END_ACK) {
        BurnCtrl::BurnCmdType type = burnCmdTypeArray[burnCmdIndex - 1];
        if (isSwitchAfterLoader && type == BurnCmdType::LOADER) {
            BYTE byte[SHAKE_HAND_SIGNAL_LEN] = {0};
            errno_t retMemcpy = memcpy_s(byte, SHAKE_HAND_SIGNAL_LEN, Global::shakeHandSignal, SHAKE_HAND_SIGNAL_LEN);
            if (retMemcpy != 0) {
                qDebug() << "Error memcpy";
                return;
            }
            SEBOOT_SHAKE_HANDS_FRAME *head = reinterpret_cast<SEBOOT_SHAKE_HANDS_FRAME *>(byte);
            head->frameType = 0x5a;
            head->frameTypeReverse = ~head->frameType;
            head->checkSum = ChannelClass::Channel::SopCrc16(
                reinterpret_cast<PBYTE>(byte), SHAKE_HAND_SIGNAL_LEN - 2); // crc16 is 2
            WriteToPort(reinterpret_cast<CHAR *>(head), SHAKE_HAND_SIGNAL_LEN);
            SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_SELOADR_CHANGE_BAUD);
            return;
        }
        ProceSeloaderEndAck(strData, chlPktHead);
    } else if (fsm == HI_BURN_FSM::FSM_BURN_UPLOAD_END_ACK) {
        HandleMulFsmAckUploadEndAck(strData, chlPktHead);
    } else {
        RmoveTimerKey();
        strData.clear();
        pkgNum = 0x0;
        isProcessOk = true;
        SetFsm(HI_BURN_FSM::FSM_WORK);
        burnCmdIndex = 0;
        retryTime = 0;
        if (chlPktHead.result == 0xA5) {
            SetResult(ERR_SELOADER_ACK_IS_FAIL);
            SetEditErrorString(stringClass.GetIdsString32889());
            return;
        }
        oneBurnTime = 0;
    }
}

void WifiBurnCtrl::HandleMulFsmAckUploadEndAck(QString &strData, SEBOOT_ACK_FRAME &chlPktHead)
{
    RmoveTimerKey();
    strData.clear();
    pkgNum = 0x0;
    isProcessOk = true;
    SetFsm(HI_BURN_FSM::FSM_WORK);
    burnCmdIndex = 0;
    retryTime = 0;
    if (chlPktHead.result == 0xA5) {
        SetResult(ERR_SELOADER_ACK_IS_FAIL);
        SetEditErrorString(stringClass.GetIdsString32889());
        return;
    }
    Sleep(100); // 延时100ms
    if (isOneTimeBurn != 0) {
        Global::CloseApp(0);
        return;
    }
}

void WifiBurnCtrl::HandleInterAck(unsigned int &dataLen, PBYTE data)
{
    if (DataConvertor::FindChar(data, dataLen, MODEM_ACK)) { // 监测确认回复信号并继续发送文件
        ackTimestamp = QDateTime::currentDateTime().toMSecsSinceEpoch();
        HandleInterAckP1();
    } else if (dataLen == 1 && DataConvertor::FindChar(data, dataLen, MODEM_C)) {
        unsigned int currentTimestamp = QDateTime::currentDateTime().toMSecsSinceEpoch();
        if (currentTimestamp >= ackTimestamp + 300) { // 300ms内返回C不处理
            HandleInterAckP2();
            ackTimestamp = currentTimestamp;
        }
    } else {
        SecureZeroMemory(data, dataLen);
        dataLen = 0;
    }
}

void WifiBurnCtrl::HandleFinalAck(unsigned int &dataLen, PBYTE data)
{
    if (data == nullptr || dataLen > MAX_BUFFER_LEN) {
        return;
    }
    for (unsigned int i = 0; i < dataLen; i++) {
        data[i] = (data[i] == 0 ? ' ' : data[i]);
    }
    QString strData = QString::fromLatin1(reinterpret_cast<CHAR *>(data));
    if (DataConvertor::FindChar(data, dataLen, MODEM_ACK)) {
        FsmWaitFinalAck(strData);
    } else if (dataLen == 1 && DataConvertor::FindChar(data, dataLen, MODEM_C)) {
        HandleInterAckP2();
    } else {
        SecureZeroMemory(data, dataLen);
        dataLen = 0;
    }
}

void WifiBurnCtrl::HandleInterAckP2()
{
    U32 readBytesAckP2 = modemPacketSize; // 默认读1024字节
    BIN_INFO info = infoArray[burnCmdIndex - 1];
    int pktLen = modemPacketSize + 5; // 1029长度
    PBYTE pBurnFile = new BYTE[pktLen];
    if (pBurnFile == nullptr) {
        return;
    }
    SecureZeroMemory(pBurnFile, pktLen);
    pBurnFile[0] = ChannelClass::Channel::GetYmodeSTX(modemPacketSize);
    pBurnFile[1]  = --pkgNum;
    pBurnFile[2] = 0xff - pkgNum; // 第2字节固定含义
    pkgNum++;
    UINT nBytesRead = 0;
    if (IsEncrypt()) {
        HandleInterAckSetBinFilePosEncrypt(info, readBytesAckP2);
        if (memoryOperation.Pos() + modemPacketSize > info.GetFileIndex() + info.GetFileSize()) { // 默认读1024字节
            readBytesAckP2 = static_cast<U32>(info.GetFileIndex() + info.GetFileSize() - memoryOperation.Pos());
        }
        nBytesRead = memoryOperation.Read(pBurnFile + 3, readBytesAckP2); // 读1024字节到偏移3字节之后
    } else {
        HandleInterAckSetBinFilePos(info, readBytesAckP2);
        if (binFile.pos() + modemPacketSize > info.GetFileIndex() + info.GetFileSize()) { // 默认读1024字节
            readBytesAckP2 = static_cast<U32>(info.GetFileIndex() + info.GetFileSize() - binFile.pos());
        }
        nBytesRead = binFile.read(reinterpret_cast<CHAR *>(pBurnFile) + 3, readBytesAckP2); // 读1024字节到偏移3字节之后
    }
    /* 计算1024字节crc从第3字节开始 */
    WORD crc = YModemClass::YModem::GetCrc(reinterpret_cast<PBYTE>(&pBurnFile[3]), modemPacketSize); // 3
    pBurnFile[pktLen - 2] = static_cast<unsigned char>(crc >> 8);                // crc右移8位放在1027上
    pBurnFile[pktLen - 1] = static_cast<unsigned char>(crc);                     // crc低位放在1028位
    singleLineWritingInfo.len = pktLen;
    memcpy_s(singleLineWritingInfo.singleLineData, CHECK_BIT, pBurnFile, CHECK_BIT);
    WriteToPort(reinterpret_cast<char *>(pBurnFile), pktLen);
    if (pBurnFile != nullptr) {
        delete [] pBurnFile;
        pBurnFile = nullptr;
    }
    isProcessOk = true;
    if (nBytesRead == 0) {
        return;
    }
}

void WifiBurnCtrl::HandleInterAckSetBinFilePos(BIN_INFO &info, U32 readBytesAckP2)
{
    if (info.GetFileSize() < static_cast<int>(readBytesAckP2)) {
        binFile.seek(info.GetFileIndex());
    } else if (binFile.pos() == info.GetFileIndex() + info.GetFileSize()) {
        if (modemPacketSize == 0) {
            binFile.seek(info.GetFileIndex() + info.GetFileSize());
        } else {
            binFile.seek(info.GetFileIndex() + info.GetFileSize() - info.GetFileSize() % modemPacketSize);
        }
    } else {
        binFile.seek(binFile.pos() - readBytesAckP2);
    }
}

void WifiBurnCtrl::HandleInterAckSetBinFilePosEncrypt(BIN_INFO &info, U32 readBytesAckP2)
{
    if (info.GetFileSize() < static_cast<int>(readBytesAckP2)) {
        memoryOperation.Seek(info.GetFileIndex());
    } else if (memoryOperation.Pos() == info.GetFileIndex() + info.GetFileSize()) {
        if (modemPacketSize == 0) {
            memoryOperation.Seek(info.GetFileIndex() + info.GetFileSize());
        } else {
            memoryOperation.Seek(info.GetFileIndex() + info.GetFileSize() - info.GetFileSize() % modemPacketSize);
        }
    } else {
        memoryOperation.Seek(memoryOperation.Pos() - readBytesAckP2);
    }
}

void WifiBurnCtrl::HandleInterAckP1()
{
    RmoveTimerKey();
    int pktLen = modemPacketSize + 5; // 1029长度
    PBYTE pBurnFile = new BYTE[pktLen];
    if (pBurnFile == nullptr) {
        return;
    }
    SecureZeroMemory(pBurnFile, pktLen);
    pBurnFile[0] = ChannelClass::Channel::GetYmodeSTX(modemPacketSize);
    pBurnFile[1] = pkgNum;
    pBurnFile[2] = 0xff - pkgNum; // 第2字节固定含义
    pkgNum++;
    U32 readBytesAckP1 = modemPacketSize; // 默认读1024字节
    BIN_INFO info = infoArray[burnCmdIndex - 1];
    UINT nBytesRead = 0;
    if (IsEncrypt()) {
        if (memoryOperation.Pos() + modemPacketSize > info.GetFileIndex() + info.GetFileSize()) {
            readBytesAckP1 = static_cast<U32>(info.GetFileIndex() + info.GetFileSize() - memoryOperation.Pos());
        }
        nBytesRead = memoryOperation.Read(pBurnFile + 3, readBytesAckP1); // 读1024字节到偏移3字节之后
    } else {
        if (binFile.pos() + modemPacketSize > info.GetFileIndex() + info.GetFileSize()) {
            readBytesAckP1 = static_cast<U32>(info.GetFileIndex() + info.GetFileSize() - binFile.pos());
        }
        nBytesRead = binFile.read(reinterpret_cast<CHAR *>(pBurnFile) + 3, readBytesAckP1); // 读1024字节到偏移3字节之后
    }
    /* 计算1024字节crc从第3字节开始 */
    WORD crc = YModemClass::YModem::GetCrc(reinterpret_cast<PBYTE>(&pBurnFile[3]), modemPacketSize);
    pBurnFile[pktLen - 2] = static_cast<unsigned char>(crc >> 8);                // crc右移8位放在1027上
    pBurnFile[pktLen - 1] = static_cast<unsigned char>(crc);                     // crc低位放在1028位
    singleLineWritingInfo.len = pktLen;
    memcpy_s(singleLineWritingInfo.singleLineData, CHECK_BIT, pBurnFile, CHECK_BIT);
    WriteToPort(reinterpret_cast<char *>(pBurnFile), pktLen);
    if (pBurnFile != nullptr) {
        delete [] pBurnFile;
        pBurnFile = nullptr;
    }
    UpdateProgress(readBytesAckP1);
    isProcessOk = true;
    HandleInterAckP1Sub(nBytesRead, info);
    if (pBurnFile != nullptr) {
        delete[] pBurnFile;
        pBurnFile = nullptr;
    }
}

void WifiBurnCtrl::HandleInterAckP1Sub(const UINT &nBytesRead, const BIN_INFO &info)
{
    EnterCS();
    if (IsEncrypt()) {
        if (fsm == HI_BURN_FSM::FSM_BURN_WAIT_INTER_ACK) {
            if (nBytesRead < modemPacketSize ||
                memoryOperation.Pos() >= info.GetFileIndex() + info.GetFileSize()) { // 长度1024字节
                SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_FINAL_ACK);
            } else {
                SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_INTER_ACK);
            }
            SetTimerByFsm();
        }
    } else {
        if (fsm == HI_BURN_FSM::FSM_BURN_WAIT_INTER_ACK) {
            if (nBytesRead < modemPacketSize ||
                binFile.pos() >= info.GetFileIndex() + info.GetFileSize()) { // 长度1024字节
                SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_FINAL_ACK);
            } else {
                SetFsm(HI_BURN_FSM::FSM_BURN_WAIT_INTER_ACK);
            }
            SetTimerByFsm();
        }
    }
    LeaveCS();
}

void WifiBurnCtrl::HandleSeloadUploadAck(unsigned int& dataLen, PBYTE data)
{
    SEBOOT_ACK_FRAME chlPktHead;
    int resDataLenUp = dataLen;
    int decodeResultUp = ChannelClass::Channel::DecodeSEBootAck(data, dataLen, chlPktHead, resDataLenUp);
    if (decodeResultUp == DECODE_PACKET_SUCCSS || decodeResultUp == DECODE_PACKET_MORE_THAN_ONE) {
        SecureZeroMemory(data + dataLen - resDataLenUp - sizeof(SEBOOT_ACK_FRAME), sizeof(SEBOOT_ACK_FRAME));
        if (memmove_s(data + dataLen - resDataLenUp - sizeof(SEBOOT_ACK_FRAME),
            sizeof(SEBOOT_ACK_FRAME) + resDataLenUp, data + (dataLen - resDataLenUp), resDataLenUp) != 0) {
            return;
        }
        dataLen = dataLen - sizeof(SEBOOT_ACK_FRAME);
        if (chlPktHead.result == 0xA5) {
            QString strPrompt;
            strPrompt= stringClass.GetIdsString32890().arg(chlPktHead.errorCode);
            SetEditErrorString(strPrompt);
            SlotKillAllTimer();
            SetFsm(HI_BURN_FSM::FSM_WORK);
            isProcessOk = true;
            burnCmdIndex = 0;
            SetResult(ERR_SELOADER_ACK_IS_FAIL);
            if (isOneTimeBurn != 0) {
                Global::CloseApp(this->result);
            }
            return;
        } else {
            SlotKillAllTimer();
            SetFsm(HI_BURN_FSM::FSM_BURN_UPLOAD_START_C);
            isProcessOk = true;

            if (commonTimer == nullptr) {
                commonTimer = new QTimer();
            }
            if (commonTimer != nullptr) {
                commonTimerEvent = TIMER_ID_UPLOAD_START_TIME;
                commonTimer->moveToThread(thread);
                commonTimer->setInterval(COMMON_TIMER_INTERVAL3000);
                commonTimer->setTimerType(Qt::PreciseTimer);
                commonTimer->setSingleShot(true);
                QMetaObject::invokeMethod(commonTimer,
                                          std::bind(static_cast<void(QTimer::*)()>(&QTimer::start), commonTimer));
                commonTimerID = commonTimer->timerId();
                connect(commonTimer, &QTimer::timeout, this,
                        &BurnCtrl::SlotBurnCtrlCommonTimerHandlerTest, Qt::DirectConnection);
                SetParamPoint(commonTimerID, nullptr);
                SetRunningItem(commonTimerID, this);
            }
        }
    }
}

void WifiBurnCtrl::HandleUploadStartC(unsigned int& dataLen, PBYTE data)
{
    if (dataLen >= 133) { // start packet 133 len
        YMODE_START_END_PACKET chlPktHead;
        int resDataLenUp = dataLen;
        U32 packetSize = 0;
        int decodeResult = ChannelClass::Channel::DecodeYmodeHeadPacket(data, dataLen, chlPktHead,
                                                                        resDataLenUp, packetSize);
        if (decodeResult != DECODE_PACKET_SUCCSS && decodeResult != DECODE_PACKET_MORE_THAN_ONE) {
            return;
        }
        SecureZeroMemory(data + dataLen - resDataLenUp - sizeof(YMODE_START_END_PACKET),
            sizeof(YMODE_START_END_PACKET));
        if (memmove_s(data + dataLen - resDataLenUp - sizeof(YMODE_START_END_PACKET),
            sizeof(YMODE_START_END_PACKET) + resDataLenUp, data + (dataLen - resDataLenUp), resDataLenUp) != 0) {
            return;
        }
        dataLen = dataLen - sizeof(YMODE_START_END_PACKET);
        m_packetSize = packetSize;
        m_resSize = packetSize;
        progressPos = 0;
        BurnCtrl::SetProgressRange(0, SHRT_MAX);
        burnFileSize = 0;
        UpdateProgress(0, m_packetSize);
        SlotKillAllTimer();
        EnterCS();
        if (fsm == HI_BURN_FSM::FSM_BURN_UPLOAD_START_C) {
            SetFsm(HI_BURN_FSM::FSM_BURN_UPLOAD_INIT_ACK);
            SetTimerByFsm();
        }
        LeaveCS();
        isProcessOk = true;
        char ctrlC[2] = { 6, 67 }; // send 2 bytes, ack is 6, start C is 67
        WriteToPort(ctrlC, 2);     // send 2 bytes
    }
}

void WifiBurnCtrl::HandleUploadInitAck(unsigned int& dataLen, PBYTE data)
{
    if (HandleUploadInitAckP3(dataLen, data) || HandleUploadInitAckP1(dataLen, data) ||
        HandleUploadInitAckP2(dataLen, data)) { // 8192以上为大包
        return;
    }
    if (chipType != ChipType::HI3372) {
        if (dataLen == 1 && data[0] == 0x04) {
            SlotKillAllTimer();
            EnterCS();
            if (fsm == HI_BURN_FSM::FSM_BURN_UPLOAD_INIT_ACK) {
                SetFsm(HI_BURN_FSM::FSM_BURN_UPLOAD_EOT_C);
                SetTimerByFsm();
            }
            LeaveCS();
            isProcessOk = true;
            char ctrlC[1] = { 67 };
            WriteToPort(ctrlC, 1);
        }
        return;
    }
    for (unsigned int i = 0; i < dataLen && dataLen < 10; i++) { // 小于10个
        if (data[i] == 0x04) {
            SlotKillAllTimer();
            EnterCS();
            if (fsm == HI_BURN_FSM::FSM_BURN_UPLOAD_INIT_ACK) {
                SetFsm(HI_BURN_FSM::FSM_BURN_UPLOAD_EOT_C);
                SetTimerByFsm();
            }
            LeaveCS();
            isProcessOk = true;
            char ctrlC[1] = { 67 };
            WriteToPort(ctrlC, 1);
        }
    }
}

bool WifiBurnCtrl::HandleUploadInitAckP2(unsigned int& dataLen, PBYTE data)
{
    if (dataLen >= 133) { // start packet 133 len
        YMODE_INFO_PACKET_SMALL chlPktHead;
        int resDataLen = dataLen;
        int decodeResult = ChannelClass::Channel::DecodeYmodeSmallPacket(data, dataLen, chlPktHead, resDataLen);
        if (decodeResult != DECODE_PACKET_SUCCSS && decodeResult != DECODE_PACKET_MORE_THAN_ONE) {
            return false;
        }
        SecureZeroMemory(data + dataLen - resDataLen - sizeof(YMODE_INFO_PACKET_SMALL),
            sizeof(YMODE_INFO_PACKET_SMALL));
        if (memmove_s(data + dataLen - resDataLen - sizeof(YMODE_INFO_PACKET_SMALL),
            sizeof(YMODE_INFO_PACKET_SMALL) + resDataLen, data + (dataLen - resDataLen), resDataLen) != 0) {
            return false;
        }
        dataLen = dataLen - sizeof(YMODE_INFO_PACKET_SMALL);
        SlotKillAllTimer();
        U32 lastResSizeAckP2 = m_resSize;
        if (m_resSize >= sizeof(chlPktHead.data)) {
            m_uploadFile.write(reinterpret_cast<CHAR*>(chlPktHead.data), sizeof(chlPktHead.data));
            m_resSize -= sizeof(chlPktHead.data);
        } else {
            m_uploadFile.write(reinterpret_cast<CHAR*>(chlPktHead.data), m_resSize);
            m_resSize = 0;
        }
        UpdateProgress(lastResSizeAckP2 - m_resSize, m_packetSize);
        EnterCS();
        if (fsm == HI_BURN_FSM::FSM_BURN_UPLOAD_INIT_ACK) {
            SetFsm(HI_BURN_FSM::FSM_BURN_UPLOAD_INIT_ACK);
            SetTimerByFsm();
        }
        LeaveCS();
        isProcessOk = true;
        char ctrlC[1] = { 6 };
        WriteToPort(ctrlC, 1);
        return true;
    }
    return false;
}

bool WifiBurnCtrl::HandleUploadInitAckP1(unsigned int& dataLen, PBYTE data)
{
    if (dataLen >= 1029) { // 1029长度
        YMODE_INFO_PACKET_LARGE chlPktHead;
        int resDataLen = dataLen;
        int decodeResult = ChannelClass::Channel::DecodeYmodeLargePacket(data, dataLen, chlPktHead, resDataLen);
        if (decodeResult != DECODE_PACKET_SUCCSS && decodeResult != DECODE_PACKET_MORE_THAN_ONE) {
            return false;
        }
        SecureZeroMemory(data + dataLen - resDataLen - sizeof(YMODE_INFO_PACKET_LARGE),
            sizeof(YMODE_INFO_PACKET_LARGE));
        if (memmove_s(data + dataLen - resDataLen - sizeof(YMODE_INFO_PACKET_LARGE),
            sizeof(YMODE_INFO_PACKET_LARGE) + resDataLen, data + (dataLen - resDataLen), resDataLen) != 0) {
            return false;
        }
        dataLen = dataLen - sizeof(YMODE_INFO_PACKET_LARGE);
        U32 lastResSizeAckP1 = m_resSize;
        SlotKillAllTimer();
        retryTime = 0;
        if (m_resSize >= sizeof(chlPktHead.data)) {
            m_uploadFile.write(reinterpret_cast<CHAR*>(chlPktHead.data), MAX_RESSIZE);
            m_resSize -= sizeof(chlPktHead.data);
        } else {
            m_uploadFile.write(reinterpret_cast<CHAR*>(chlPktHead.data), m_resSize);
            m_resSize = 0;
        }
        UpdateProgress(lastResSizeAckP1 - m_resSize, m_packetSize);
        EnterCS();
        if (fsm == HI_BURN_FSM::FSM_BURN_UPLOAD_INIT_ACK) {
            SetFsm(HI_BURN_FSM::FSM_BURN_UPLOAD_INIT_ACK);
            SetTimerByFsm();
        }
        LeaveCS();
        isProcessOk = true;
        char ctrlC[1] = { 6 };
        WriteToPort(ctrlC, 1);
        return true;
    }
    return false;
}

bool WifiBurnCtrl::HandleUploadInitAckP3(unsigned int& dataLen, PBYTE data)
{
    if (dataLen >= 8195) { // 8195长度
        YMODE_INFO_PACKET_8K chlPktHead;
        int resDataLen = dataLen;
        int decodeResult = ChannelClass::Channel::DecodeYmode8KPacket(data, dataLen, chlPktHead, resDataLen);
        if (decodeResult != DECODE_PACKET_SUCCSS && decodeResult != DECODE_PACKET_MORE_THAN_ONE) {
            return false;
        }
        SecureZeroMemory(data + dataLen - resDataLen - sizeof(YMODE_INFO_PACKET_8K),
            sizeof(YMODE_INFO_PACKET_8K));
        if (memmove_s(data + dataLen - resDataLen - sizeof(YMODE_INFO_PACKET_8K),
            sizeof(YMODE_INFO_PACKET_8K) + resDataLen, data + (dataLen - resDataLen), resDataLen) != 0) {
            return false;
        }
        dataLen = dataLen - sizeof(YMODE_INFO_PACKET_8K);
        U32 lastResSizeAckP3 = m_resSize;
        SlotKillAllTimer();
        if (m_resSize >= sizeof(chlPktHead.data)) {
            m_uploadFile.write(reinterpret_cast<CHAR*>(chlPktHead.data), sizeof(chlPktHead.data));
            m_resSize -= sizeof(chlPktHead.data);
        } else {
            m_uploadFile.write(reinterpret_cast<CHAR*>(chlPktHead.data), m_resSize);
            m_resSize = 0;
        }
        UpdateProgress(lastResSizeAckP3 - m_resSize, m_packetSize);
        EnterCS();
        if (fsm == HI_BURN_FSM::FSM_BURN_UPLOAD_INIT_ACK) {
            SetFsm(HI_BURN_FSM::FSM_BURN_UPLOAD_INIT_ACK);
            SetTimerByFsm();
        }
        LeaveCS();
        isProcessOk = true;
        char ctrlC[1] = { 6 };
        WriteToPort(ctrlC, 1);
        return true;
    }
    return false;
}

void WifiBurnCtrl::HandleUploadEotC(unsigned int &dataLen, PBYTE data)
{
    if (dataLen >= 133) { // end packet 133 len
        YMODE_START_END_PACKET chlPktHead;
        int resDataLen = dataLen;
        U32 packetSize = 0;
        int decodeResult = ChannelClass::Channel::DecodeYmodeHeadPacket(
            data, dataLen, chlPktHead, resDataLen, packetSize);
        if (decodeResult != DECODE_PACKET_SUCCSS && decodeResult != DECODE_PACKET_MORE_THAN_ONE) {
            return;
        }
        SecureZeroMemory(data + dataLen - resDataLen - sizeof(YMODE_START_END_PACKET),
            sizeof(YMODE_START_END_PACKET));
        if (memmove_s(data + dataLen - resDataLen - sizeof(YMODE_START_END_PACKET),
            sizeof(YMODE_START_END_PACKET) + resDataLen, data + (dataLen - resDataLen), resDataLen) != 0) {
            return;
        }
        dataLen = dataLen - sizeof(YMODE_START_END_PACKET);
        SetEditErrorString(stringClass.GetIdsString32893());
        SlotKillAllTimer();
        if (m_uploadFile.isOpen()) {
            m_uploadFile.close();
        }
        EnterCS();
        if (fsm == HI_BURN_FSM::FSM_BURN_UPLOAD_EOT_C) {
            SetFsm(HI_BURN_FSM::FSM_BURN_UPLOAD_END_ACK);
            SetTimerByFsm();
        }
        LeaveCS();
        isProcessOk = true;
        char ctrlC[1] = { 6 };
        WriteToPort(ctrlC, 1);
    }
}

void WifiBurnCtrl::SendCtrl()
{
    sendCtrlCount++;
    if (ctrlPeriod == 0) {
        ctrlPeriod = 10; // 异常时默认为10
    }
    if (sendCtrlCount >= static_cast<int>(sendBurnTimeout / ctrlPeriod)) {
        SetEditErrorString(stringClass.GetIdsString32894());
        SetResult(TIMER_ID_WAIT_HISILICON);
        if (isOneTimeBurn != 0) {
            Global::CloseApp(this->result);
        } else {
            ResetByMode();
        }
        return;
    }
    BurnCtrl::BurnCmdType type = GetCurrentCmdType();
    if (fsm == HI_BURN_FSM::FSM_WAIT_INTERRUPT_FLAG) {
        char ctrl[1] = { 3 };
        WriteToPort(ctrl, 1);
    } else if (fsm >= HI_BURN_FSM::FSM_BURN_UPLOAD_START_C && fsm <= HI_BURN_FSM::FSM_BURN_UPLOAD_EOT_C) {
        // 必须要这个顺序和下面的握手不能调换顺序
        char ctrl[1] = { 67 };
        SecureZeroMemory(cDataArray, sizeof(cDataArray));
        u32DataLen = 0;
        WriteToPort(ctrl, 1);
    } else if (fsm == HI_BURN_FSM::FSM_CHECK_IF_CONNECT) {
        WriteToPort(reinterpret_cast<CHAR *>(Global::shakeHandSignal), SHAKE_HAND_SIGNAL_LEN);
    } else {
        SendCtrlSub(type);
    }
}

void WifiBurnCtrl::SendCtrlSub(const BurnCmdType &type)
{
    if ((burnCmdIndex == 0 || type == BurnCmdType::LOADER || type == BurnCmdType::UNKNOWN) &&
        bootType == BOOT_ROM && chipType == ChipType::WIFIDW31) {
        if (countTimeOut == 5) { // countTimeOut 5
            countTimeOut = 0;
            WriteToPort(reinterpret_cast<CHAR *>(Global::shakeHandSignal), SHAKE_HAND_SIGNAL_LEN);
            return;
        }
        unsigned char a[1] = {0xFF};
        WriteToPort(reinterpret_cast<CHAR *>(a), 1);
        countTimeOut++ ;
    } else if ((burnCmdIndex == 0 || type == BurnCmdType::LOADER || type == BurnCmdType::UNKNOWN) &&
               bootType == BOOT_ROM) {
        if (isSwitchAfterLoader) {
            WriteToPort(reinterpret_cast<CHAR *>(Global::constShakeHandSignal), SHAKE_HAND_SIGNAL_LEN);
        } else {
            WriteToPort(reinterpret_cast<CHAR *>(Global::shakeHandSignal), SHAKE_HAND_SIGNAL_LEN);
        }
    } else if (bootType == BOOT_LOADER && burnCmdIndex == 0) {
        WriteToPort(reinterpret_cast<CHAR *>(g_flashBootBurn), FLASH_BOOT_BURN_LEN);
    } else {
        char ctrl[1] = { 3 };
        WriteToPort(ctrl, 1);
    }
}

void WifiBurnCtrl::StartConnectSetting()
{
    if (burnCmdIndex >= burnCmdArray.size()) {
        burnCmdIndex = 0;
    }
    if (IsSecConn()) {
        SetFsm(HI_BURN_FSM::FSM_WAIT_RANDOM);
        ctrlPeriod = SEND_CTRL_PEROID_SEC;
        port.SetOneTimeReadByte(0);

        if (commonTimer != nullptr) {
            commonTimer = new QTimer();
        }
        if (commonTimer != nullptr) {
            commonTimerEvent = TIMER_ID_WAIT_RANDOM;
            commonTimer->moveToThread(thread);
            commonTimer->setInterval(TIMER_ID_WAIT_RANDOM_3921_TIMEOUT);
            commonTimer->setTimerType(Qt::PreciseTimer);
            commonTimer->setSingleShot(true);
            QMetaObject::invokeMethod(commonTimer,
                std::bind(static_cast<void(QTimer::*)()>(&QTimer::start), commonTimer));
            commonTimerID = commonTimer->timerId();
            connect(commonTimer, &QTimer::timeout, this, &BurnCtrl::SlotBurnCtrlCommonTimerHandlerTest,
                    Qt::DirectConnection);
            SetParamPoint(commonTimerID, nullptr);
            SetRunningItem(commonTimerID, this);
        }
    } else {
        if (bootType == BOOT_ROM) {
            UpdateComSetting(OPEN_SERIAL_PORT_DEFAULT_BAUD_RATE, OPEN_SERIAL_PORT_DEFAULT_DATA_BIT,
                             OPEN_SERIAL_PORT_DEFAULT_STOP_BIT, QSerialPort::NoParity,
                             OPEN_SERIAL_PORT_DEFAULT_FLOWCTRL);
            EnterCS();
            if (isReopenCom) {
                port.ReInitPort();
            }
            UpdateComSettingWithoutClose();
            LeaveCS();
            isShutDown = false;
            SetFsm(HI_BURN_FSM::FSM_WAIT_SHAKE_HANDS_ACK);
            SetFileInfo(GetCurrentFilePath());
        } else {
            ctrlPeriod = 10; // 10ms period
            SetFsm(HI_BURN_FSM::FSM_WAIT_FLASH_SHAKE_HANDS_ACK);
        }
        port.SetOneTimeReadByte(20); // min 20 bytes
    }
    interruptFlag = CHL_INTERRUPT_FLAG_ROMBOOT;
}

